package com.gougou.rpc.custom;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.UUID;

/**
 * 用于创建RPC服务代理对象（通过jdk代理接口的方法创建代理对象）
 * Created by EX-ZHANZHENQIANG001 on 2018-05-02.
 */
public class RpcProxy {

    private String serverAddress;

    private ServiceDiscovery serviceDiscovery;

    public RpcProxy(ServiceDiscovery serviceDiscovery) {
        this.serviceDiscovery = serviceDiscovery;
    }

    public RpcProxy(String serverAddress) {
        this.serverAddress = serverAddress;
    }

    /**
     * 根据传入的接口类Class对象创建代理对象并返回
     * @param interfaceClass
     * @param <T>
     * @return
     */
    public <T> T create(Class<?> interfaceClass) {
        return (T) Proxy.newProxyInstance(
                //使用接口类的类加载器
                interfaceClass.getClassLoader(),
                //传入接口类的Class对象
                new Class[]{interfaceClass},
                //代理方法逻辑处理
                new InvocationHandler() {
                    //代理方法实现
                    public Object invoke(Object proxy, Method method, Object[] args)
                            throws Throwable {
                        //创建RpcRequest，并设置封装被代理类的属性
                        RpcRequest request = new RpcRequest();
                        //设置请求ID
                        request.setRequestId(UUID.randomUUID().toString());
                        //拿到声明这个方法的业务接口名称
                        request.setClassName(method.getDeclaringClass().getName());
                        //设置被调用方法的名称
                        request.setMethodName(method.getName());
                        //设置参数类型
                        request.setParameterTypes(method.getParameterTypes());
                        //设置参数值
                        request.setParameters(args);
                        //从zookeeper中查找可用的服务
                        if(serviceDiscovery != null) {
                            serverAddress = serviceDiscovery.discover();
                        }

                        //随机获取服务的地址
                        String[] array = serverAddress.split(":");
                        //获取服务器IP、端口
                        String host = array[0];
                        int port = Integer.valueOf(array[1]);
                        //创建Netty实现的RpcClient，链接服务端
                        RpcClient rpcClient = new RpcClient(host, port);
                        //通过netty向服务端发送消息
                        RpcResponse response = rpcClient.send(request);
                        //处理返回结果
                        if(response.isError()) {
                            throw response.getError();
                        } else {
                            return response.getResult();
                        }
                    }
                });
    }


}
